import React, { useRef, useState, useEffect } from 'react';
import { Button, Spin, Space, Slider, Upload, message } from 'antd';
import { UploadOutlined } from '@ant-design/icons';
import Icon from '../Icon';
import './Videoplay.scss';

const WIDTH = 600;
const HEIGHT = 400;
const FPS = 60;
const DEFAULT_VOLUME = 0.5;
const Videoplay = (props) => {
  const { src, showFps = false } = props;
  const [srcUrl, setSrcUrl] = useState(src);
  const [video, setVideo] = useState(null); // videoDom
  const [canvas, setCanvas] = useState(null); // canvasDom
  const [videoSpin, setVideoSpin] = useState(false); // 视频加载状态
  const [drawParams, setDrawParams] = useState({}); // 视频绘制参数 {cxt ,x, y, width, height}
  const [isPaused, setIsPaused] = useState(true); // 是否暂停状态
  const [videoCurrent, setVideoCurrent] = useState(0);
  const videoRef = useRef(null);
  const canvasRef = useRef(null);
  const shotRef = useRef(null);

  /* 预加载 */
  const preload = (url) => {
    if (!url) return;
    const v = videoRef.current;
    const c = canvasRef.current;
    const cxt = c.getContext('2d');
    v.src = url;
    setCanvas(c);
    const playTimer = setInterval(() => {
      setVideoSpin(true);
      if (v.readyState === 4) {
        setVideoSpin(false);
        clearInterval(playTimer);
        // 默认音量 50%
        v.volume = DEFAULT_VOLUME;

        /* 视频绘制预处理 */
        const { videoWidth, videoHeight } = v;
        // 横纵比
        const aspectRatio = videoWidth / videoHeight;
        // 宽高计算, 视频居中
        let width = WIDTH;
        let height = HEIGHT;
        let x = 0;
        let y = 0;
        if (aspectRatio > 1) {
          height = width / aspectRatio;
          y = (HEIGHT - height) / 2;
        } else {
          width = height * aspectRatio;
          x = (WIDTH - width) / 2;
        }
        setDrawParams({ cxt, x, y, width, height });
        setVideo(v);
        // 绘制预览帧
        cxt.drawImage(v, x, y, width, height);
      }
    }, 100);
  };

  /* 视频绘制到canvas */
  const copyToCanvas = ({ cxt, x, y, width = WIDTH, height = HEIGHT }) => {
    const option = [video, x, y, width, height];
    const timer = setInterval(() => {
      cxt.clearRect(0, 0, WIDTH, HEIGHT);
      cxt.drawImage(...option);
      setVideoCurrent(video.currentTime);
      if (video.ended || video.paused) {
        // 视频结束或暂停则停止绘制
        clearInterval(timer);
        setIsPaused(video.paused);
      }
    }, 1000 / FPS);
  };

  /* 播放 */
  const vPlay = () => {
    video.play();
    setIsPaused(video.paused);
    copyToCanvas({ ...drawParams });
  };

  /* 暂停 */
  const vPause = () => {
    video.pause();
    setIsPaused(video.paused);
  };

  /* 播放进度修改 */
  const timeChange = (value) => {
    video.currentTime = value;
  };

  /* 音量 */
  const setVolume = (value) => {
    video.volume = value / 100;
  };

  /* 静音/解除静音 */
  const mutedChange = () => {
    video.muted = !video.muted;
  };

  /* 额外功能 */

  /* 截图 */
  const screenshot = () => {
    const cxt = shotRef.current.getContext('2d');
    cxt.clearRect(0, 0, WIDTH, HEIGHT);
    cxt.drawImage(canvas, 0, 0, WIDTH, HEIGHT);
  };

  /* 图片下载 */
  const saveAsPNG = () => {
    const screenCanvas = shotRef.current;
    try {
      const base64Data = screenCanvas.toDataURL('image/png');
      downloadFile('crop.png', base64Data);
    } catch (err) {
      message.error('网络地址无法截图');
    }
  };

  /* 上传配置 */
  const upConfig = {
    showUploadList: false,
    beforeUpload(file) {
      setSrcUrl(getFileUrl(file));
      message.success('上传成功');
      return false;
    },
  };

  /* 文件转url */
  const getFileUrl = (file) => {
    let url;
    if (window.navigator.userAgent.indexOf('MSIE') >= 1) {
      // IE
      url = file.value;
    } else if (window.navigator.userAgent.indexOf('Firefox') > 0) {
      // Firefox
      url = window.URL.createObjectURL(file);
    } else if (window.navigator.userAgent.indexOf('Chrome') > 0) {
      // Chrome
      url = window.URL.createObjectURL(file);
    }
    return url;
  };

  /* base64下载到本地 */
  const downloadFile = (fileName, content) => {
    const aLink = document.createElement('a');
    const blob = base64ToBlob(content); // new Blob([content]);
    const evt = document.createEvent('HTMLEvents');
    evt.initEvent('click', true, true); // initEvent 不加后两个参数在FF下会报错  事件类型，是否冒泡，是否阻止浏览器的默认行为
    aLink.download = fileName;
    aLink.href = URL.createObjectURL(blob);
    aLink.click();
  };

  /* base64转blob */
  const base64ToBlob = (code) => {
    const parts = code.split(';base64,');
    const contentType = parts[0].split(':')[1];
    const raw = window.atob(parts[1]);
    const rawLength = raw.length;
    const uInt8Array = new Uint8Array(rawLength);
    for (let i = 0; i < rawLength; i += 1) {
      uInt8Array[i] = raw.charCodeAt(i);
    }
    return new Blob([uInt8Array], { type: contentType });
  };

  useEffect(() => {
    preload(srcUrl);
  }, [srcUrl]);
  return (
    <div data-component="video-play">
      <div style={{ display: 'flex' }}>
        <Spin spinning={videoSpin} delay={500}>
          <div className="videoDiv" style={{ height: HEIGHT, width: WIDTH }}>
            <video className="videoDom" width={200} ref={videoRef}>
              您的浏览器暂不支持视频播放，请更换浏览器
            </video>
            <canvas ref={canvasRef} width={WIDTH} height={HEIGHT}>
              您的浏览器暂不支持视频播放，请更换浏览器
            </canvas>
            {showFps ? <span className="rate">fps:{FPS}</span> : ''}
          </div>
          <Space>
            <Upload {...upConfig}>
              <Button type="primary">
                <UploadOutlined /> 选择视频
              </Button>
            </Upload>
            <Button
              type="primary"
              disabled={!srcUrl}
              onClick={() => {
                if (isPaused) {
                  vPlay();
                } else {
                  vPause();
                }
              }}
            >
              {isPaused ? '播放' : '暂停'}
            </Button>
            <Button type="primary" disabled={!srcUrl} onClick={screenshot}>
              截图
            </Button>
            <Button type="primary" disabled={!srcUrl} onClick={saveAsPNG}>
              下载截图
            </Button>
            <div className="volume">
              <Button
                type="link"
                icon={
                  <Icon
                    type={
                      video?.muted
                        ? 'tfReactyinliangguanbi'
                        : 'tfReactyinliangkai'
                    }
                  />
                }
                disabled={!srcUrl}
                onClick={mutedChange}
              />
              <Slider
                style={{ width: 120 }}
                defaultValue={DEFAULT_VOLUME * 100}
                onChange={setVolume}
                disabled={!srcUrl}
              />
            </div>
          </Space>
          <Slider
            disabled={!srcUrl}
            max={video ? video.duration : 0}
            value={videoCurrent}
            step={0.01}
            onChange={timeChange}
          />
        </Spin>
        <div>
          <canvas ref={shotRef} width={WIDTH} height={HEIGHT}>
            您的浏览器暂不支持视频播放，请更换浏览器
          </canvas>
        </div>
      </div>
    </div>
  );
};

export default Videoplay;
